package com.sunday.common.easy.excel.api;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.sunday.common.core.asserts.BusinessAssert;
import com.sunday.common.core.converter.MapperConvert;
import com.sunday.common.core.enums.ErrorCodeEnum;
import com.sunday.common.core.gson.GsonUtils;
import com.sunday.common.core.remoting.base.response.Response;
import com.sunday.common.core.remoting.rest.response.RestResponse;
import com.sunday.common.easy.excel.data.PseudoData;
import com.sunday.common.easy.excel.dto.ListBlacklistLibraryReqDTO;
import com.sunday.common.easy.excel.dto.ListBlacklistLibraryResDTO;
import com.sunday.common.easy.excel.dto.UploadBlacklistLibraryReqDTO;
import com.sunday.common.easy.excel.handler.EasyExcelHandler;
import com.sunday.common.easy.excel.listener.EasyExcelReadListener;
import com.sunday.common.easy.excel.vo.DownloadBlacklistLibraryReqVO;
import com.sunday.common.easy.excel.vo.DownloadBlacklistLibraryResVO;
import com.sunday.common.easy.excel.vo.TemplateBlacklistLibraryResVO;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.*;

/**
 * @Description: demo程序
 */
@Slf4j
@RestController
@RequestMapping("/commodity")
public class BlacklistLibraryApi {

    /**
     * @Description: 模板附件execl导出方案
     */
//    @PostMapping("template")
    @GetMapping("template")
    public void template(HttpServletResponse httpServletResponse) throws IOException {
        /**
         * 实体execl导出方案 推荐此方案
         */
        EasyExcelHandler.download(httpServletResponse, "中文自定义附件名称-实体execl导出方案",
                (resp) -> EasyExcel.write(resp.getOutputStream(), TemplateBlacklistLibraryResVO.class)
                        // 文件下载并且失败的时候返回json（默认失败了会返回一个有部分数据的Excel）
                        .autoCloseStream(Boolean.FALSE)
                        .sheet("黑名单")
                        .doWrite(Arrays.asList()));

//        /**
//         * 附件execl导出方案
//         */
//        EasyExcelHandler.download(httpServletResponse, "附件execl导出方案",
//                (resp) -> {
//                    IoUtils.copy(getClass().getClassLoader().getResourceAsStream("templates/template.xlsx"), resp.getOutputStream());
//                    EasyExcel.write(resp.getOutputStream()).autoCloseStream(Boolean.FALSE);
//                });
    }

    /**
     * @Description: 导出数据-模拟数据
     */
//    @PostMapping("download")
    @GetMapping("download")
    public void download(HttpServletResponse httpServletResponse) throws IOException {
        DownloadBlacklistLibraryReqVO downloadBlacklistLibraryReqVO = new DownloadBlacklistLibraryReqVO();
//    public void download(@RequestBody DownloadBlacklistLibraryReqVO downloadBlacklistLibraryReqVO, HttpServletResponse httpServletResponse) throws IOException {
        String url = "233";
        log.info("{}", url);
        EasyExcelHandler.download(httpServletResponse, "中文自定义附件名称-模拟数据",
                (resp) -> {
                    // 这里 需要指定写用哪个class去写
                    try (ExcelWriter excelWriter = EasyExcel.write(resp.getOutputStream(), DownloadBlacklistLibraryResVO.class).autoCloseStream(Boolean.FALSE).build()) {
                        // 这里注意 如果同一个sheet只要创建一次
                        WriteSheet writeSheet = EasyExcel.writerSheet("模拟黑名单Sheet").build();
                        // 去调用写入,这里我调用了N次，实际使用时根据数据库分页的总的页数来
                        ListBlacklistLibraryReqDTO listBlacklistLibraryReqDTO = MapperConvert.map(downloadBlacklistLibraryReqVO, ListBlacklistLibraryReqDTO.class);
//                        listBlacklistLibraryReqDTO.setCurrentUser(CurrentUser.of(CurrentUserHolder.getUserInfo()));
                        while (true) {
                            Response<List<ListBlacklistLibraryResDTO>> response = PseudoData.getData();
                            //检测是否响应正常
                            BusinessAssert.isSuccess(response, ErrorCodeEnum.B0_313);
                            //检测是否存在响应值
                            if (response.getBody().isEmpty()) {
                                excelWriter.write(Arrays.asList(), writeSheet);
                                break;
                            }
                            List<DownloadBlacklistLibraryResVO> libraryResVOS = Optional.ofNullable(response.getBody())
                                    .map(data -> data.stream()
                                            .map(o -> MapperConvert.map(o, DownloadBlacklistLibraryResVO.class))
                                            .toList())
                                    .orElse(Collections.emptyList());
                            //提升GC释放时间
                            response.setBody(null);
                            //设置最后查询id
                            listBlacklistLibraryReqDTO.setLastId(libraryResVOS.get(libraryResVOS.size() - 1).getId());
                            excelWriter.write(libraryResVOS, writeSheet);
                            //检测是否有必要执行下一轮查询
                            if (libraryResVOS.size() < listBlacklistLibraryReqDTO.getPageSize()) {
                                break;
                            }
                        }
                    }
                });
    }

    /**
     * @Description: 上传附件execl
     */
    @PostMapping("upload")
    public RestResponse upload(@RequestParam("files") MultipartFile file) {

        EasyExcelReadListener.Counter counter = EasyExcelReadListener.Counter.create();
        /**
         * 上传附件execl , 分段解析测试 （推荐）
         * 分段提交要关注的是每个批次执行后的结果，及最终结果的汇总
         */
        List<Response> responses = new ArrayList<>();
        try {
            BusinessAssert.state(file != null, () ->
                            EasyExcel.read(BusinessAssert.maybeGet(file::getInputStream, ErrorCodeEnum.B0_313),
                                    UploadBlacklistLibraryReqDTO.BlacklistLibraryDTO.class,
                                    new EasyExcelReadListener<UploadBlacklistLibraryReqDTO.BlacklistLibraryDTO>(
                                            2,
                                            5,
//                                false,
                                            (cachedDataList) -> {
                                                log.info("{} 条数据，开始存储数据库！", cachedDataList.size());
                                                cachedDataList.stream().forEach(blacklistLibraryDTO -> log.info("{}", blacklistLibraryDTO));
                                                responses.add(Response.ok());
                                                log.info("存储数据库成功！");
                                            },
                                            counter)
                            ).sheet().doRead()
            );
        } catch (Exception e) {
            log.info("{}", counter);
            log.info("{}", GsonUtils.DEFAULT.toJson(responses));
            throw e;
        }

//        /**
//         * 上传附件execl , 全量解析方案 （不推荐）
//         */
//        BusinessAssert.access(file != null, () -> {
//            EasyExcel.read(BusinessAssert.maybeGet(file::getInputStream, ErrorCodeEnum.A0_420),
//                    UploadBlacklistLibraryReqDTO.BlacklistLibraryDTO.class,
//                    new EasyExcelAllReadListener<UploadBlacklistLibraryReqDTO.BlacklistLibraryDTO>(
//                            5,
////                            false,
//                            (cachedDataList) -> {
//                                log.info("{} 条数据，开始存储数据库！", cachedDataList.size());
//                                cachedDataList.stream().forEach(blacklistLibraryDTO -> log.info("{}", blacklistLibraryDTO));
//                                log.info("存储数据库成功！");
//                            })
//            ).sheet().doRead();
//        });
//
        return RestResponse.ok();
    }

}